home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / LAN / ALAP.I < prev    next >
Encoding:
Text File  |  1991-08-18  |  23.4 KB  |  3 lines

  1. ⓪ ⓪ IMPLEMENTATION MODULE ALAP;⓪ (*$H+,Z+,S-,R-*)⓪ ⓪ FROM SYSTEM IMPORT ADR, ASSEMBLER, BITNUM, BYTE, WORD, LONGWORD, ADDRESS, SHIFT;⓪ FROM GEMDOS IMPORT Super;⓪ FROM Storage IMPORT ALLOCATE;⓪ ⓪ (* I/O-Routinen für Testausgaben *)⓪ IMPORT InOut;⓪ ⓪ CONST NMI_Mask = $0700;⓪ ⓪((* alle Zeitwerte sind in µs angegeben *)⓪(bitTime = 5 (* 4.34 *);⓪(byteTime = 39;⓪(IDGslottime = 200;⓪(maxIFGtime = 400; (* 200 ist für ENQ->ACK offenbar zu klein. *)⓪(minIDGtime = 2*maxIFGtime;⓪ ⓪ CONST CTLA = $FFFF8C81;⓪ ⓪ (* -------------------------------------------------- *)⓪ ⓪ PROCEDURE resetRx;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(MOVEA.W #CTLA,A1⓪(; resetRx⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #$D0,(A1)       ; disableRx⓪(MOVEQ   #2,D0⓪&flushFIFO:⓪(TST.B   2(A1)⓪(DBRA    D0,flushFIFO⓪(MOVE.B  #$30,(A1)       ; reset error⓪(MOVE.B  #$20,(A1)       ; enable IR on next Rx⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #rxEnable,(A1)  ; enableRx⓪$END⓪"END resetRx;⓪"(*$L=*)⓪"⓪ ⓪ CONST  rnda = 1664525;     (* Knuth S.102 Zeile 26 *)⓪'rndc = 117;         (* teilerfremd mit 2^32 für max. Periode 2^32 *)⓪ ⓪ PROCEDURE random;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; IN: D0.W max-Wert minus 1, OUT: D0.W 0..max-1⓪(MOVE.W  D0,-(A7)⓪(MOVE.L  seed,D0⓪(BNE     isInit⓪(; seek initialisieren⓪(MOVEM.L A0-A2,-(A7)⓪(MOVE    #17,-(A7)⓪(TRAP    #14⓪(ADD.L   D0,seed⓪(TRAP    #14⓪(ADDQ.L  #2,A7⓪(MOVEM.L (A7)+,A0-A2⓪(LSL.L   #8,D0⓪(ADD.L   D0,seed⓪&isInit:⓪(MOVE.L  D0,D1⓪(MOVE.L  D0,D2⓪(SWAP    D2⓪(MOVE.L  D3,-(A7)⓪(MOVE.L  #rnda,D3⓪(MULU    D3,D0⓪(MULU    D3,D2⓪(SWAP    D3⓪(MULU    D3,D1⓪(MOVE.L  (A7)+,D3⓪(SWAP    D1⓪(CLR.W   D1⓪(SWAP    D2⓪(CLR.W   D2⓪(ADD.L   D1,D0⓪(ADD.L   D2,D0⓪(ADDI.L  #rndc,D0⓪(MOVE.L  D0,seed⓪(MOVE.W  (A7)+,D1⓪(BEQ     rtn0⓪(MOVE.W  D0,D2⓪(CLR.W   D0⓪(SWAP    D0⓪(DIVU    D1,D0⓪(MOVE.W  D2,D0⓪(DIVU    D1,D0⓪(SWAP    D0⓪(RTS⓪&rtn0⓪(MOVEQ   #0,D0⓪$END⓪"END random;⓪"(*$L=*)⓪ ⓪ PROCEDURE WriteFrame (REF packet: aPacket; no: CARDINAL);⓪"VAR n: CARDINAL;⓪"BEGIN⓪$FOR n:= 1 TO 5 DO⓪&IF n > packet.length THEN⓪(InOut.WriteString ('   ');⓪&ELSE⓪(InOut.WriteHex (LONG (packet.frame.rawData [n]), 3);⓪&END⓪$END;⓪$FOR n:= 6 TO no DO⓪&IF n <= packet.length THEN⓪(InOut.WriteHex (LONG (packet.frame.rawData [n]), 3);⓪(IF (ORD (packet.frame.rawData [n]) >= 32) AND⓪+(ORD (packet.frame.rawData [n]) < 128) THEN⓪*InOut.Write ('/');⓪*InOut.Write (CHAR(packet.frame.rawData [n]));⓪(END⓪&END⓪$END;⓪$InOut.WriteString (' ');⓪"END WriteFrame;⓪ ⓪ PROCEDURE WriteStatus (status: FrameStatus);⓪"BEGIN⓪$CASE status OF⓪&|badframeCRC: InOut.WriteString ('>badframeCRC<')⓪&|badframeSize: InOut.WriteString ('>badframeSize<');⓪&|badframeType: InOut.WriteString ('>badframeType<')⓪&|overrunError: InOut.WriteString ('>overrunError<')⓪&|underrunError: InOut.WriteString ('>underrunError<')⓪&|lostAddress: InOut.WriteString ('>lost address<')⓪&|lapACKframe: InOut.WriteString ('>ACKframe<')⓪&|lapENQframe: InOut.WriteString ('>ENQframe<');⓪&|lapRTSframe: InOut.WriteString ('>RTSframe<');⓪&|lapCTSframe: InOut.WriteString ('>CTSframe<');⓪&|lapDATAframe: InOut.WriteString ('>DATAframe<');⓪&|noFrame: InOut.WriteString ('no frame!');⓪$ELSE⓪&InOut.WriteString ('unknown frame!');⓪$END;⓪"END WriteStatus;⓪ ⓪ (* --------------------------- *)⓪ ⓪ FORWARD AcquireAddress;⓪ FORWARD TransmitPacket;⓪ FORWARD TransmitFrame;⓪ FORWARD ReceiveFrame (VAR packet: ptrPacket): FrameStatus;⓪ FORWARD ReceiveLinkMgmt (VAR packet: ptrPacket): ReceiveStatus;⓪ FORWARD IR_Handler;⓪ FORWARD GetFrame;⓪ ⓪ PROCEDURE NewPacketBuffer;⓪"VAR p, prev, last: ptrPacket; sr: CARDINAL;⓪"BEGIN⓪$ASSEMBLER⓪(MOVE    SR,sr(A6)⓪(MOVE    #$2500,SR⓪$END;⓪$NEW (p);⓪$IF p # NIL THEN⓪&IF packetBuffers = 0 THEN⓪(headPacket:= p;⓪(tailPacket:= p;⓪(last:= p⓪&ELSE⓪(prev:= headPacket;⓪(WHILE prev^.next # tailPacket DO⓪*prev:= prev^.next⓪(END;⓪(last:= prev^.next;⓪(prev^.next:= p⓪&END;⓪&INC (packetBuffers);⓪&WITH p^ DO⓪(next:= last;⓪(status:= undefined;⓪(no:= packetBuffers⓪&END;⓪$END;⓪$ASSEMBLER⓪(MOVE    sr(A6),SR⓪$END;⓪"END NewPacketBuffer;⓪ ⓪ PROCEDURE ResetReceiveBuffer;⓪"BEGIN⓪$tailPacket:= headPacket⓪"END ResetReceiveBuffer;⓪ ⓪ TABLE.W SCCInitData:⓪*$09C0, $0420, $0AE0, $0600, $077E, $0C06, $0D00, $0EC0,⓪*$03D0, $0B70, $0E21, $0560, $0F00, $0108,⓪*$0200 + ADR (IR_Vector) DIV 4, $0908, $0300+rxEnable, 0;⓪ ⓪ (*$L-*)⓪ ⓪ PROCEDURE Init;⓪"(* IN: D0.B: proposed address, 0 if none *)⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.B  D0,myAddress⓪(CLR     backoff⓪(CLR.B   deferHistory⓪(CLR.B   collsnHistory⓪(⓪(JSR     NewPacketBuffer⓪(JSR     NewPacketBuffer⓪(JSR     NewPacketBuffer⓪$⓪(; Init Timer A⓪(MOVEA.W #$FA00,A0⓪(MOVE.B  #$00,$19(A0)    ; TACR: Timer Stop⓪(ANDI.B  #$DF,$13(A0)    ; IMRA: Mask Timer A IR⓪(ORI.B   #$20,$07(A0)    ; IERA: Enable Timer-A Pending Bit⓪(MOVE.B  #$DF,$0B(A0)    ; IPRA: Clear Timer-A Pending Bit⓪ ⓪%; *** SCC initialisieren ***⓪%;⓪%; Die Clock an RTxCA ist 3.672 MHz, benötigte Baudrate ist 230400 Bit/s.⓪%; Dazu müßte die Clock auf 1/16 geteilt werden.⓪%; Da für Receive DPLL verwendet wird, und DPLL den 16fachen Clk⓪%; braucht, wird trotzdem kein Teiler verwendet. Stattdessen wird⓪%; über den BRG geteilt.⓪%;⓪%; Der SCC arbeitet im Interrupt-Betrieb. Es wird der Non-Auto-Vektor-⓪%; Modus verwendet, auf Adr. $360. Der IR läuft im Level 5.⓪%; Da nur eine einzige IR-Quelle benutzt wird (IR on 1st Rx Char or⓪%; special condition), wird die vector-includes-status-Option nicht⓪%; verwerdet.⓪%;⓪ ⓪(; GIOffBit ($7F);⓪(MOVE.W  #$7F,-(A7)⓪(MOVE    #29,-(A7)⓪(TRAP    #14⓪(ADDQ.L  #4,A7⓪(⓪(MOVE.L  #IR_Handler,IR_Vector⓪(⓪(LEA     SCCInitData,A0⓪(MOVEA.W #CTLA,A1⓪$l1: MOVE.W  (A0)+,D0⓪(BEQ     e1⓪(MOVE.W  D0,D1⓪(LSR     #8,D1⓪(MOVE.B  D1,(A1)⓪(NOP⓪(MOVE.B  D0,(A1)⓪(BRA     l1⓪$e1:⓪(MOVE.B  myAddress,D0⓪(JSR     AcquireAddress⓪(⓪(CLR     deferCount⓪(CLR     collsnCount⓪(CLR     DataFramesOut⓪(CLR     RTSFramesOut⓪(CLR     CTSFramesOut⓪$END⓪"END Init;⓪ ⓪ VAR acqFrame: aTxFrame;⓪ ⓪ PROCEDURE AcquireAddress;⓪"(* IN: D0.B: proposed address, 0 if none *)⓪"BEGIN⓪$ASSEMBLER⓪(; *** choose address ***⓪(BSR     getNewAddress⓪(CLR     fAdrValid⓪(SUBQ    #2,A7⓪&acqlp2:⓪(CLR     fAdrInUse⓪(MOVE.W  #wksTries,(A7)⓪&acqlp:⓪(; TransmitPacket (myAddress, lapENQ, ENQframe.dataField, 0)⓪(LEA     acqFrame,A0⓪(MOVE.B  myAddress,D0⓪(MOVE.B  D0,aTxFrame.ctrl.dstAddr(A0)⓪(MOVE.B  D0,aTxFrame.ctrl.srcAddr(A0)⓪(MOVE.B  #lapENQ,aTxFrame.ctrl.lapType(A0)⓪(CLR.W   aTxFrame.dataCnt1(A0)⓪(CLR.W   aTxFrame.dataCnt2(A0)⓪(JSR     TransmitPacket⓪(CMPI    #transmitOK,D0⓪(BEQ     adrIsUsed⓪(TST     fAdrInUse⓪(BEQ     adrNotUsed⓪ adrIsUsed:⓪(MOVEQ   #0,D0⓪(BSR     getNewAddress⓪(BRA     acqlp2⓪ adrNotUsed:⓪(SUBQ    #1,(A7)⓪(BNE     acqlp⓪(ADDQ    #2,A7⓪(MOVE    #1,fAdrValid⓪(RTS⓪ ⓪ getNewAddress:⓪(TST.B   D0⓪(BNE     takeIt⓪(MOVEQ   #127,D0⓪(JSR     random⓪(ADDQ    #1,D0⓪&takeIt:⓪(MOVE.B  D0,myAddress⓪(; setAddress⓪(MOVEA.W #CTLA,A1⓪(MOVE.B  #6,(A1)⓪(MOVE.B  myAddress,(A1)⓪$END;⓪"END AcquireAddress;⓪ ⓪ PROCEDURE TransmitPacket;⓪"(* IN:  A0: ^aTxFrame⓪%OUT: D0.W TransmitStatus *)⓪ ⓪"PROCEDURE BitCount;⓪$BEGIN⓪&ASSEMBLER⓪*; In: D0.B, Out: D1.W /D0-D2/⓪*MOVEQ   #0,D1⓪*MOVEQ   #7,D2⓪'l: LSR.B   #1,D0⓪*BCC     c⓪*ADDQ    #1,D1⓪'c: DBRA    D2,l⓪&END⓪$END BitCount;⓪"⓪"BEGIN (* TransmitPacket *)⓪$ASSEMBLER⓪(TST     fAdrInUse⓪(BEQ     notInUse⓪(MOVEQ   #dupAddress,D0⓪(RTS⓪¬InUse:⓪(MOVE.L  A0,-(A7)⓪(⓪(LEA     RTSframe,A1⓪(MOVE.B  aTxFrame.ctrl.dstAddr(A0),aTxFrame.ctrl.dstAddr(A1)⓪(MOVE.B  myAddress,aTxFrame.ctrl.srcAddr(A1)⓪(MOVE.B  #lapRTS,aTxFrame.ctrl.lapType(A1)⓪(CLR.W   aTxFrame.dataCnt1(A1)⓪(CLR.W   aTxFrame.dataCnt2(A1)⓪(⓪(MOVE.B  collsnHistory,D0⓪(BSR     BitCount⓪(CMPI    #2,D1⓪(BLS     c1⓪(⓪(; increase backoff because of too many collisions⓪(CLR.B   collsnHistory⓪(MOVE.W  backoff,D0⓪(BEQ     c2⓪(LSL     #1,D0⓪(CMPI    #16,D0⓪(BLS     c3⓪(MOVEQ   #16,D0⓪(BRA     c3⓪$c2: MOVEQ   #2,D0⓪$c3: MOVE    D0,backoff⓪(⓪$c1: MOVE.B  deferHistory,D0⓪(BSR     BitCount⓪(CMPI    #2,D1⓪(BCC     c4⓪(⓪(; decrease backoff if no defers recently⓪(CLR.B   deferHistory⓪(LSR.W   backoff⓪(⓪$c4: ; shift history data⓪(LSL     collsnHistory⓪(LSL     deferHistory⓪(⓪(CLR.W   deferTries⓪(CLR.W   collsnTries⓪(MOVE.W  backoff,lclbackoff⓪(⓪(MOVEA.W #CTLA,A1⓪(MOVEA.W #$FA00,A2⓪(⓪ again1: ; *** main loop ***⓪(⓪(; *** defer while there are other transmissions in progress ***⓪(⓪(; carrierSense?⓪(BTST    #4,CTLA⓪(BNE.W   noCarrier⓪(⓪(BRA     defer1⓪(⓪&defer2:⓪(ADDQ.W  #1,deferCount⓪(ADDQ.W  #1,deferTries⓪(CMPI.W  #maxDefers,deferTries⓪(BLS     defer1⓪(⓪(; *** Error: too many defers ***⓪(MOVE.W  #excessDefers,D0⓪(BRA.W   exit⓪(⓪&defer1:⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; defer⓪(CMPI    #2,lclbackoff⓪(BCC     c5⓪(MOVE    #2,lclbackoff⓪&c5:⓪(BSET    #0,deferHistory⓪(⓪(; wait for packet to pass⓪(; Delay: maxFrameSize * 1.5 * byteTime (39µs) = maxFrameSize * 58.5 Zyklen⓪(MOVE    #maxFrameSize,D1⓪(MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #36,$1F(A2)     ; TADR: Set Timer Count⓪(MOVE.B  #1,$19(A2)      ; TACR: Timer Start (Teiler: 1/4)⓪(BRA     c6⓪$l6: BTST    #4,CTLA⓪(BNE     c7              ; kein Carrier mehr⓪(BTST    #5,$0B(A2)⓪(BEQ     c6⓪(MOVE.B  #$DF,$0B(A2)    ; time over: Clear Timer-A Pending Bit⓪$c6: DBRA    D1,l6⓪(⓪(; something is wrong: ResetRx⓪(JSR     resetRx⓪$c7: MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪&noCarrier:⓪(⓪(; resetMissingClock⓪(MOVE.B  #14,(A1)⓪(MOVE.B  #$41,(A1)⓪(⓪(; wait for min. IDG time after packet or idle line⓪(MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #minIDGtime DIV 4,$1F(A2)      ; Set Timer Count⓪(MOVE.B  #2,$19(A2)      ; TACR: Timer Start (Teiler: 1/10)⓪$l7: BTST    #4,CTLA⓪(BEQ     defer1          ; erneut Carrier aufgetreten⓪(BTST    #5,$0B(A2)      ; IPRA⓪(BEQ     l7⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; wait additional backoff time, deferring to others⓪(MOVE    lclbackoff,D0⓪(BEQ     n8⓪(ADDQ    #1,D0⓪(JSR     random⓪$n8: MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #IDGslottime DIV 4,$1F(A2)      ; Set Timer Count⓪(MOVE.B  #2,$19(A2)      ; TACR: Timer Start (Teiler: 1/10)⓪(BRA     c8⓪$l8: BTST    #4,CTLA⓪(BEQ     defer2          ; erneut Carrier aufgetreten⓪(BTST    #5,$0B(A2)      ; IPRA⓪(BEQ     l8⓪(MOVE.B  #$DF,$0B(A2)    ; time over: Clear Timer-A Pending Bit⓪$c8: DBRA    D0,l8⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; missing clock?⓪(MOVE.B  #10,(A1)⓪(TST.B   (A1)            ; RR10⓪(BMI     defer2⓪(⓪(; *** send RTS ***⓪(⓪(MOVE.L  (A7),A0⓪(CMPI.B  #lapENQ,aTxFrame.ctrl.lapType(A0)⓪(BEQ     sndENQ⓪(LEA     RTSframe,A0⓪ sndENQ: MOVE    SR,D2⓪(ORI     #NMI_Mask,SR⓪(ADDQ.W  #1,RTSFramesOut⓪(JSR     TransmitFrame⓪(⓪(; enableRx⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #rxEnable,(A1)⓪(⓪(MOVE    #1,fCTSexpected⓪(MOVE    D2,SR⓪(; *** wait for CTS ***⓪(SUBQ.L  #4,A7⓪(MOVE.L  A7,(A3)+⓪(MOVEM.L A1/A2,-(A7)⓪(JSR     ReceiveFrame/⓪(MOVEM.L (A7)+,A1/A2⓪(ADDQ.L  #4,A7⓪(CLR     fCTSexpected⓪(⓪(TST     fAdrInUse⓪(BEQ     noDup⓪(⓪(; *** Error: duplicate address ***⓪(MOVE.W  #dupAddress,D0⓪(BRA.W   exit⓪(⓪ noDup:  MOVE.L  (A7),A0⓪(CMPI.B  #$FF,aTxFrame.ctrl.dstAddr(A0)⓪(BNE     chkCTS⓪(; broadcast-Transmit auswerten⓪(CMPI    #noFrame,D0⓪(BNE     error1⓪(BRA     send2⓪ chkCTS: CMPI    #lapCTSframe,D0⓪(BNE     error1⓪(CMPI.B  #lapENQ,aTxFrame.ctrl.lapType(A0)⓪(BEQ     error1⓪(⓪ send2:  ; *** eigentliches Paket senden ***⓪(MOVE    SR,D2⓪(BREAK ;ORI     #NMI_Mask,SR⓪(ADDQ.W  #1,DataFramesOut⓪(JSR     TransmitFrame⓪(⓪(; enableRx⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #rxEnable,(A1)⓪(⓪(MOVE    D2,SR⓪(MOVE.W  #transmitOK,D0⓪(BRA.W   exit⓪(⓪ error1  ; assume collision because we didn't receive the expected CTS⓪(ADDQ    #1,collsnCount⓪(BSET    #0,collsnHistory⓪(ADDQ    #1,collsnTries⓪(CMPI    #maxCollsns,collsnTries⓪(BHI     excssC⓪(⓪(MOVE.W  lclbackoff,D0⓪(BEQ     c12⓪(LSL     #1,D0⓪(CMPI    #16,D0⓪(BLS     c13⓪(MOVEQ   #16,D0⓪(BRA     c13⓪#c12: MOVEQ   #2,D0⓪#c13: MOVE    D0,lclbackoff⓪(⓪(BRA     again1⓪(⓪ excssC: ; *** Error: too many collisions ***⓪(MOVE.W  #excessCollsns,D0⓪ exit:   ADDQ.L  #4,A7⓪$END;⓪"END TransmitPacket;⓪ ⓪ PROCEDURE TransmitFrame;⓪"BEGIN⓪$ASSEMBLER⓪(; A0: ^aTxFrame, A1: CTLA, A2: $FFFFFA00⓪(; enableTxDrivers⓪(MOVE.B  #5,(A1)⓪(MOVE.B  #setRTS,(A1)⓪(⓪(; Pause f. Sync-Pulse (1 Bit: 1.5 * bitTime (6.51µs) = 16 Zyklen)⓪(MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #4,$1F(A2)      ; TADR: Set Timer Count⓪(MOVE.B  #1,$19(A2)      ; TACR: Timer Start (Teiler: 1/4)⓪%l: BTST    #5,$0B(A2)      ; IPRA⓪(BEQ     l⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; disableTxDrivers⓪(MOVE.B  #5,(A1)⓪(MOVE.B  #$60,(A1)⓪(⓪(; Pause f. Sync-Pulse (1 Bit: 1.5 * bitTime (6.51µs) = 16 Zyklen)⓪(MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #4,$1F(A2)      ; TADR: Set Timer Count⓪(MOVE.B  #1,$19(A2)      ; TACR: Timer Start (Teiler: 1/4)⓪%l2 BTST    #5,$0B(A2)      ; IPRA⓪(BEQ     l2⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; enableTxDrivers, enableTx⓪(MOVE.B  #5,(A1)⓪(MOVE.B  #txEnable,(A1)⓪(⓪(; disableRx⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #$D0,(A1)⓪(⓪(; 2 * txFlag⓪(; Delay: 2 * 1.5 * byteTime (39µs) = 116 Zyklen⓪(MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #70,$1F(A2)     ; TADR: Set Timer Count⓪(MOVE.B  #1,$19(A2)      ; TACR: Timer Start (Teiler: 1/4)⓪%l3 BTST    #5,$0B(A2)      ; IPRA⓪(BEQ     l3⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; resetCRC⓪(MOVE.B  #$80,(A1)⓪(⓪(BSR     TxChar⓪(BSR     TxChar⓪(BSR     TxChar⓪(ADDQ.L  #1,A0⓪(MOVE.L  (A0)+,A2⓪(MOVE.W  (A0)+,D0⓪(DBRA    D0,nextChar1⓪(BRA     allSent1⓪(⓪%TxChar:⓪(BTST    #2,(A1)⓪(BEQ     TxChar⓪(MOVE.B  (A0)+,2(A1)⓪(RTS⓪(⓪%nextChar1:⓪(BTST    #2,(A1)⓪(BEQ     nextChar1⓪(MOVE.B  (A2)+,2(A1)⓪(DBRA    D0,nextChar1⓪%allSent1:⓪(MOVE.L  (A0)+,A2⓪(MOVE.W  (A0)+,D0⓪(DBRA    D0,nextChar2⓪(BRA     allSent2⓪%nextChar2:⓪(BTST    #2,(A1)⓪(BEQ     nextChar2⓪(MOVE.B  (A2)+,2(A1)⓪(DBRA    D0,nextChar2⓪%allSent2:⓪(⓪(; resetUnderrun⓪(MOVE.B  #$C0,(A1)⓪(⓪(; TxFCS: wait for underrun⓪%notUnder:⓪(BTST    #6,(A1)⓪(BEQ     notUnder⓪(⓪(; TxFlag (?)⓪%notEmpty2:⓪(BTST    #2,(A1)⓪(BEQ     notEmpty2⓪(⓪(; enableTxDrivers, disableTx⓪(MOVE.B  #5,(A1)⓪(MOVE.B  #setRTS,(A1)⓪(⓪(; txONEs (?)⓪(; Delay: 1.5 * byteTime (39µs) = 58 Zyklen⓪(MOVEA.W #$FA00,A2⓪(MOVE.B  #$DF,$0B(A2)    ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #35,$1F(A2)     ; TADR: Set Timer Count⓪(MOVE.B  #1,$19(A2)      ; TACR: Timer Start (Teiler: 1/4)⓪%l4 BTST    #5,$0B(A2)      ; IPRA⓪(BEQ     l4⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(⓪(; disableTxDrivers⓪(MOVE.B  #5,(A1)⓪(MOVE.B  #$60,(A1)⓪(⓪(; resetMissingClock⓪(MOVE.B  #14,(A1)⓪(MOVE.B  #$41,(A1)⓪$END;⓪"END TransmitFrame;⓪ ⓪ (*$L+*)⓪ ⓪ PROCEDURE ReceivePacket (VAR dstParam: anAddress;⓪9VAR srcParam: anAddress;⓪9VAR typeParam: aLAPtype;⓪9VAR dataParam: aDataField;⓪9VAR dataLength: INTEGER);⓪"VAR status: ReceiveStatus; packet: ptrPacket;⓪"BEGIN⓪$REPEAT UNTIL (ReceiveLinkMgmt (packet) = receiveOK) OR InOut.KeyPressed ();⓪$WITH packet^.frame DO⓪&dstParam:= dstAddr;⓪&srcParam:= srcAddr;⓪&typeParam:= lapType;⓪&dataParam:= dataField (*!!! hier werden 600 Byte kopiert -> Ptr verw.*)⓪$END;⓪"END ReceivePacket;⓪ ⓪ PROCEDURE ReceiveLinkMgmt (VAR packet: ptrPacket): ReceiveStatus;⓪"⓪"VAR status: ReceiveStatus;⓪&rcvdStatus: FrameStatus;⓪&sr: CARDINAL;⓪"⓪"BEGIN⓪$ASSEMBLER⓪(MOVE    SR,sr(A6)⓪(MOVE    #$2500,SR⓪$END;⓪$status:= receiving;⓪$REPEAT⓪&rcvdStatus:= ReceiveFrame (packet);⓪&IF rcvdStatus # noFrame THEN⓪(InOut.WriteCard (packet^.no, 1); InOut.Write (' ');⓪(WriteFrame (packet^,99);⓪(InOut.WriteLn;⓪(WriteStatus (rcvdStatus); InOut.WriteLn;⓪&END;⓪&CASE rcvdStatus OF⓪&|badframeCRC, badframeSize, badframeType, overrunError, underrunError,⓪'lostAddress:⓪(status:= frameError⓪&|lapACKframe:⓪&|lapENQframe:⓪((* wird nun schon beim Empfang erledigt *)⓪(HALT⓪((*⓪*IF fAdrValid THEN⓪,WITH ACKframe DO⓪.dstAddr:= packet^.frame.srcAddr;⓪.srcAddr:= myAddress;⓪.lapType:= lapACK⓪,END;⓪,TransmitFrame (ACKframe, 3);⓪*ELSE⓪,fAdrInUse:= TRUE⓪*END;⓪*status:= nullReceive⓪(*)⓪&|lapRTSframe:⓪((* wird nun schon beim Empfang erledigt *)⓪(HALT⓪((*⓪*IF fAdrValid THEN⓪,WITH CTSframe DO⓪.dstAddr:= headPacket^.frame.srcAddr;⓪.srcAddr:= myAddress;⓪.lapType:= lapCTS⓪,END;⓪,TransmitFrame (CTSframe, 3);⓪*ELSE⓪,fAdrInUse:= TRUE;⓪,status:= nullReceive⓪*END;⓪(*)⓪&|lapDATAframe:⓪(IF fAdrValid THEN⓪*status:= receiveOK⓪(ELSE⓪*ASSEMBLER⓪+;BREAK⓪*END;⓪*fAdrInUse:= TRUE;⓪*status:= nullReceive⓪(END;⓪&|noFrame:⓪(status:= nullReceive⓪&ELSE⓪&END⓪$UNTIL status # receiving;⓪$ASSEMBLER⓪(MOVE    sr(A6),SR⓪$END;⓪$RETURN status⓪"END ReceiveLinkMgmt;⓪ ⓪ PROCEDURE ReceiveFrame (VAR packet: ptrPacket): FrameStatus;⓪"⓪"VAR status: FrameStatus;⓪ ⓪"BEGIN⓪$ASSEMBLER⓪(MOVEA.W #CTLA,A1⓪(MOVEA.W #$FA00,A2⓪(MOVE.L  tailPacket,A0⓪(⓪(; *** warten auf Frame-Empfang (IR o. Polling) ***⓪(⓪(MOVEQ   #0,D1⓪(⓪$l1: MOVE.B  #$DF,$0B(A2)               ; IPRA: Clear Timer-A Pending Bit⓪(MOVE.B  #maxIFGtime DIV 4,$1F(A2)  ; TADR: Set Timer Count⓪(MOVE.B  #2,$19(A2)                 ; TACR: Timer Start (Teiler: 1/10)⓪$l0: ; zuerst prüfen, ob evtl. noch ein Frame zu pollen ist,⓪(; auch wenn noch weitere Pakete schon im Puffer warten.⓪(MOVE.B  #3,(A1)⓪(BTST.B  #5,(A1)         ; RR3: Rx IR pending?⓪(BNE     pollFrame⓪(CMPA.L  headPacket,A0⓪(BNE     gotFrame⓪(BTST    #5,$0B(A2)      ; time over?⓪(BEQ     l0⓪(; IR-Receive nochmal prüfen, falls IR zw. vorigem CMP und Time-Chk kam.⓪(CMPA.L  headPacket,A0⓪(BNE     gotFrame⓪(⓪((*⓪(TST     test⓪(BEQ     timeout⓪(⓪(ADDQ    #1,D1⓪(BRA     l1⓪(*)⓪(⓪$timeout:⓪(; time out⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(MOVE.L  packet(A6),A0⓪(CLR.L   (A0)⓪(MOVE    #noFrame,status(A6)⓪(BRA.W   exit2⓪(⓪$gotFrame:⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(BRA     exit⓪(⓪$pollFrame:⓪(MOVE    SR,D2⓪(ORI     #NMI_Mask,SR⓪(MOVE.B  #$00,$19(A2)    ; TACR: Timer Stop⓪(JSR     GetFrame⓪(MOVE.B  #1,(A1)⓪(MOVE.B  #$08,(A1)⓪(MOVE    D2,SR⓪(⓪$exit:⓪(MOVE.L  tailPacket,D0⓪(MOVE.L  packet(A6),A0⓪(MOVE.L  D0,(A0)⓪(MOVE.L  D0,A0⓪(MOVE    aPacket.status(A0),status(A6)⓪(MOVE.L  aPacket.next(A0),tailPacket⓪(⓪$exit2:⓪$END;⓪$RETURN status⓪"END ReceiveFrame;⓪ ⓪ PROCEDURE IR_Handler;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(ORI     #NMI_Mask,SR⓪(MOVEM.L A0-A2/D0-D1,-(A7)⓪(⓪(MOVEA.W #$FA00,A2⓪(MOVEA.W #CTLA,A1⓪(JSR     GetFrame⓪(⓪(ADDQ.W  #1,Interrupts⓪(⓪(MOVEM.L (A7)+,A0-A2/D0-D1⓪(RTE⓪$END;⓪"END IR_Handler;⓪"(*$L=*)⓪ ⓪ PROCEDURE GetFrame;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; overrun?⓪(MOVE.B  #1,(A1)   ; RR1⓪(BTST.B  #5,(A1)⓪(BNE     isOverrun⓪(⓪(MOVE.L  headPacket,A0⓪(⓪(MOVE.B  2(A1),D0                ; 1. char sofort holen⓪(MOVE.B  D0,aPacket.frame(A0)⓪(⓪(MOVE.B  #2,4(A1)⓪(BTST.B  #0,4(A1)                ; RR2B⓪(BNE     specCond⓪(⓪(MOVEQ   #100,D1⓪&wait2:⓪(BTST    #0,(A1)⓪(DBNE    D1,wait2⓪(; overrun?⓪(MOVE.B  #1,(A1)   ; RR1⓪(BTST.B  #5,(A1)⓪(BNE     isOverrun⓪(⓪(MOVE.B  2(A1),aPacket.frame+1(A0)⓪(⓪(MOVEQ   #2,D0⓪(BRA     nextChar⓪(⓪$specCond:⓪(⓪$again:⓪(CLR     D0⓪(⓪$loop2:⓪(; overrun?⓪(MOVE.B  #1,(A1)   ; RR1⓪(BTST.B  #5,(A1)⓪(BEQ     noOverrun⓪(⓪$isOverrun:⓪(MOVE    D0,aPacket.length(A0)⓪(MOVE.W  #overrunError,aPacket.status(A0)⓪(BRA.W   exit2⓪(⓪$timeOut:⓪(MOVE    D0,aPacket.length(A0)⓪(MOVE.W  #noFrame,aPacket.status(A0)⓪(BRA.W   exit2⓪(⓪$noOverrun:⓪(MOVEQ   #100,D1 ;!!! Wert OK?⓪&wait4:⓪(BTST    #0,(A1)⓪(DBNE    D1,wait4⓪(BEQ     timeOut⓪(⓪(; *** read data ***⓪(CMPI.W  #maxFrameSize,D0        ; incomingLength⓪(BCS     getChar⓪(⓪$sizeError:⓪(MOVE    D0,aPacket.length(A0)⓪(MOVE.W  #badframeSize,aPacket.status(A0)⓪(BRA.W   exit2⓪(⓪$getChar:⓪(; headPacket^.frame.rawData [incomingLength]:= rxData ()⓪(MOVE.B  2(A1),aPacket.frame(A0,D0.W)  ; RR8⓪(ADDQ.W  #1,D0             ; incomingLength⓪(⓪$nextChar:⓪$noDataNow:⓪(; end of frame?⓪(MOVE.B  #1,(A1)   ; RR1⓪(TST.B   (A1)⓪(BPL     loop2⓪(⓪(SUBQ.W  #2,D0           ; incomingLength⓪(MOVE    D0,aPacket.length(A0)⓪(⓪(CMPI.W  #minFrameSize,D0⓪(BCS     sizeError⓪(⓪(; resetRx⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #$D0,(A1)       ; disableRx⓪(⓪(; CRC OK?⓪(MOVE.B  #1,(A1)   ; RR1⓪(BTST.B  #6,(A1)⓪(BEQ     crcOK⓪(⓪(MOVE.W  #badframeCRC,aPacket.status(A0)⓪(BRA.W   exit2⓪(⓪$crcOK:⓪(; Stimmt 1. Byte (unsere Adr. oder #$FF)?⓪(MOVE.B  aPacket.frame(A0),D0⓪(CMPI.B  #$FF,D0⓪(BEQ     adrOK⓪(CMP.B   myAddress,D0⓪(BEQ     adrOK⓪(⓪(MOVE.W  #lostAddress,aPacket.status(A0)⓪(BRA.W   exit2⓪(⓪%adrOK:⓪(; *** frameDone ***⓪(⓪(TST.W   fAdrValid⓪(BEQ     notValid⓪(⓪(MOVE.B  aPacket.frame.lapType(A0),D0⓪(BMI     ctrlFrame⓪(⓪(MOVE.W  #lapDATAframe,aPacket.status(A0)⓪(BRA.W   exit2⓪(⓪&ctrlFrame:⓪(CMPI.B  #lapENQ,D0⓪(BEQ     isENQ⓪(CMPI.B  #lapACK,D0⓪(BEQ     isACK⓪(CMPI.B  #lapRTS,D0⓪(BEQ     isRTS⓪(CMPI.B  #lapCTS,D0⓪(BEQ     isCTS⓪&badFrame:⓪(MOVE.W  #badframeType,aPacket.status(A0)⓪(BRA     exit2⓪&isENQ:⓪(MOVE.W  #lapENQframe,aPacket.status(A0)⓪(⓪(BRA     exit2⓪&isACK:⓪(MOVE.W  #lapACKframe,aPacket.status(A0)⓪(MOVE.W  #1,fAdrInUse⓪(BRA     exit2⓪&isRTS:⓪(MOVE.W  #lapRTSframe,aPacket.status(A0)⓪(BRA     exit2⓪&isCTS:⓪(MOVE.W  #lapCTSframe,aPacket.status(A0)⓪(TST.W   fCTSexpected⓪(BNE     exit2⓪(; das muß wieder hier rein (s. NOTES):⓪(MOVE.W  #1,fAdrInUse⓪(BRA     badFrame⓪(BRA     isNoFrame ;!!!testweise⓪(⓪¬Valid:⓪(CMPI.B  #$FF,aPacket.frame.dstAddr(A0)⓪(BEQ     exit2⓪(⓪(;BREAK⓪(MOVE    #1,fAdrInUse⓪&isNoFrame⓪(MOVE.W  #noFrame,aPacket.status(A0)⓪(⓪$exit2:⓪(⓪(MOVEQ   #2,D0⓪&flushFIFO:⓪(TST.B   2(A1)⓪(DBRA    D0,flushFIFO⓪(⓪(; resetMissingClock⓪(;MOVE.B  #14,(A1)⓪(;MOVE.B  #$41,(A1)⓪(⓪(; reset error⓪(MOVE.B  #$30,(A1)⓪(⓪(; reset IUS⓪(MOVE.B  #$38,(A1)⓪(⓪(; resetMissingClock⓪(MOVE.B  #14,(A1)⓪(MOVE.B  #$41,(A1)⓪(⓪(⓪(CMPI.W  #lapENQframe,aPacket.status(A0)⓪(BNE     noENQ⓪(⓪(; ACK senden⓪(⓪(CLR.W   -(A7)⓪(MOVE.B  #lapACK,-(A7)⓪(BRA     sendCtrlFrame⓪(⓪&noENQ:⓪(⓪(CMPI.W  #lapRTSframe,aPacket.status(A0)⓪(BNE     noRTS⓪(⓪(; CTS senden, falls kein Broadcast⓪(⓪(CMPI.B  #$FF,aPacket.frame.dstAddr(A0)⓪(BEQ     noCTS⓪(CLR.W   -(A7)⓪(SUBQ.L  #4,A7⓪(CLR.W   -(A7)⓪(SUBQ.L  #4,A7⓪(MOVE.B  #lapCTS,-(A7)⓪&sendCtrlFrame:⓪(MOVE.B  aPacket.frame.srcAddr(A0),D0⓪(LSL     #8,D0⓪(MOVE.B  myAddress,D0⓪(MOVE.W  D0,-(A7)⓪(MOVE.L  A7,A0⓪(ADDQ.W  #1,CTSFramesOut⓪(JSR     TransmitFrame⓪(ADDA.W  #16,A7⓪(MOVE.L  headPacket,A0⓪&noCTS:⓪(MOVE.W  #noFrame,aPacket.status(A0)⓪(⓪&noRTS:⓪(⓪(ADDQ.W  #1,FramesReceived⓪(⓪(MOVE.L  aPacket.next(A0),A0⓪(MOVE.L  A0,headPacket⓪(⓪(MOVE.B  #$20,(A1)         ; enable IR on next Rx⓪(⓪(MOVE.B  #3,(A1)⓪(MOVE.B  #rxEnable,(A1)  ; enableRx⓪(⓪(; more IRs?⓪(BTST    #0,(A1)⓪(BNE     again⓪$END⓪"END GetFrame;⓪"(*$L=*)⓪ ⓪ BEGIN⓪"packetBuffers:= 0;⓪ END ALAP.⓪ ə
  2. (* $FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$00003AF1$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$00004A3B$00004919$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$000030B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8$FFEFD9B8Ç$000058A6T.......T.......T.......T.......T.......T.......T.......T.......T.......T.......$FFF006F0$000058A6$00005978$00003746$000001EC$0000371D$000037D9$00003640$000030A5$00003B02$00002DC7$00005886$FFF006F0$000058A6$00005883$00005876îÇé*)
  3.